/*
 * Copyright 2009 Yannick Stucki (yannickstucki.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.yannickstucki.android.musicqueue.old;

import android.app.NotificationManager;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.view.KeyEvent;

import com.yannickstucki.android.musicqueue.R;
import com.yannickstucki.android.musicqueue.util.Logger;

/**
 * The service that runs in the background and plays the music.
 * 
 * @author Yannick Stucki (yannickstucki@gmail.com)
 * 
 */
public class PlayerService extends Service {

  /**
   * The maximal delay in milliseconds between two clicks on the head set which
   * still triggers a double click.
   */
  private static final int DOUBLE_CLICK_DELAY = 150;

  /**
   * The index used in the notification which shows the current playing song.
   */
  private static final int NOTIFICATION_INDEX = 1;

  /**
   *
   */
  public boolean destroyed = false;

  /**
   * The song manager is needed so the service knows which song to play.
   */
  private SongManager songManager;

  /**
   * The class that actually plays the songs.
   */
  private MediaPlayer mediaPlayer;


  /**
   * Somehow playPause is triggered while starting up and this shouldn't be
   * needed.
   * 
   */
  private boolean firstPlayPause = true;

  /**
   * If true, the head set got unplugged while the music was running. Therefore
   * the music has to resume when the head set is plugged in again.
   * 
   */
  private boolean headSetUnplugged = false;

  /**
   * If this is true, the music should resume when the current call ends.
   */
  private boolean musicInterruptedByCall = false;

  /**
   * Handles the plugging / unplugging of the head set.
   */
  private HeadSetPlugReceiver headSetPlugReceiver = new HeadSetPlugReceiver();

  /**
   * Handles interrupting calls.
   */
  private MyPhoneStateListener phoneListener;

  /**
   * The shared preferences to receive whether the headphone button should be
   * used or not.
   */
  private SharedPreferences settings;

  @Override
  public void onRebind(Intent intent) {
    Logger.out("service on rebind");
    super.onRebind(intent);
  }

  @Override
  public void onStart(Intent intent, int startId) {
    Logger.out("service on start");
    super.onStart(intent, startId);
  
  }

  @Override
  public boolean onUnbind(Intent intent) {
    Logger.out("service on unbind");
    return super.onUnbind(intent);
  }

  /**
   * Registers the phone state listener so it receives events.
   */
  private TelephonyManager telephonyManager;

  /**
   * Handles media button clicks.
   */
  private MediaButtonReceiver mediaButtonReceiver;

  /**
   * Used to display notifications in the top bar.
   */
  private NotificationManager notificationManager;

  /**
   * Binder between the Activity {@link MusicQueue} and this service.
   */
  private final IBinder binder = new LocalBinder();

  /**
   * Local binder implementation that returns this service.
   */
  public class LocalBinder extends Binder {

    /**
     * Returns this service.
     */
    public PlayerService getService() {
      return PlayerService.this;
    }
  }

  @Override
  public void onCreate() {
    super.onCreate();
    Logger.out("PlayerService.onCreate");
    mediaButtonReceiver = new MediaButtonReceiver(this.getString(R.string.headset_key));
    mediaPlayer = new MediaPlayer();
    notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
    this.setForeground(true);
    this.registerReceiver(headSetPlugReceiver, new IntentFilter(
        "android.intent.action.HEADSET_PLUG"));

    this.registerReceiver(mediaButtonReceiver, new IntentFilter(
        "android.intent.action.MEDIA_BUTTON"));

    phoneListener = new MyPhoneStateListener();
    telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
    telephonyManager.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    this.destroyed = true;
    Logger.out("PlayerService.onDestroy");

    mediaPlayer.stop();
    mediaPlayer.release();
  
    notificationManager.cancel(NOTIFICATION_INDEX);
    this.unregisterReceiver(headSetPlugReceiver);
    this.unregisterReceiver(mediaButtonReceiver);
    telephonyManager.listen(phoneListener, PhoneStateListener.LISTEN_NONE);
   
  }

  // Service stuff
  @Override
  public IBinder onBind(Intent intent) {
    return binder;
  }


  /**
   * Inner class for handling interruption on incoming phone calls.
   */
  private class MyPhoneStateListener extends PhoneStateListener {
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
      if (state == TelephonyManager.CALL_STATE_IDLE && musicInterruptedByCall
          && !mediaPlayer.isPlaying()) {
        musicInterruptedByCall = false;
        //playPause();
      } else { // state ringing or off hook
        if (mediaPlayer.isPlaying()) {
          musicInterruptedByCall = true;
         // playPause();
        }
      }
    }
  }

  /**
   * Inner class for handling the plugging and unplugging of the head set.
   */
  private class HeadSetPlugReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
      int state = intent.getExtras().getInt("state");
      if (firstPlayPause) {
        firstPlayPause = false;
      } else {
        if (mediaPlayer.isPlaying() && state == 0) {
          headSetUnplugged = true;
          //playPause();
        }
        if (!mediaPlayer.isPlaying() && state == 1 && headSetUnplugged) {
          headSetUnplugged = false;
         // playPause();
        }
      }
    }
  }

  /**
   * Inner class for handling the media button.
   */
  private class MediaButtonReceiver extends BroadcastReceiver {

    /**
     * Used to detect double clicks on the media button.
     */
    private long lastMediaButtonClick = System.currentTimeMillis();

    /**
     * Key to access the preferences.
     */
    private String headsetKey;

    /**
     * Constructor to set the head set key.
     */
    public MediaButtonReceiver(String headsetKey) {
      this.headsetKey = headsetKey;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
      if (settings.getBoolean(headsetKey, false)) {
        KeyEvent keyEvent = (KeyEvent) intent.getExtras().get("android.intent.extra.KEY_EVENT");
        if (keyEvent != null) {
          if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
            if (System.currentTimeMillis() - lastMediaButtonClick < DOUBLE_CLICK_DELAY) {
              songManager.remove(0);
            } else {
             // playPause();
            }
          }
          lastMediaButtonClick = System.currentTimeMillis();
        }
        this.abortBroadcast();
      }
    }
  }
}
